package com.lln.cjcx.service.impl;
import com.google.gson.Gson;
import com.lln.cjcx.pojo.MyOkHttpClient;
import com.lln.cjcx.pojo.SearchCondition;
import com.lln.cjcx.pojo.Term;
import com.lln.cjcx.pojo.grade.Grade;
import com.lln.cjcx.pojo.grade.GradeDetail;
import com.lln.cjcx.pojo.grade.TermGrade;
import com.lln.cjcx.pojo.grade.all.AllTermGrade;
import com.lln.cjcx.pojo.grade.current.CurrentTempGrade;
import com.lln.cjcx.pojo.grade.current.CurrentTermGrade;
import com.lln.cjcx.pojo.grade.detail.Detail;
import com.lln.cjcx.pojo.grade.detail.Records;
import com.lln.cjcx.service.GradeSearchService;
import com.lln.cjcx.value.UrlValue;
import kotlin.jvm.internal.Intrinsics;
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import org.jetbrains.annotations.NotNull;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.springframework.stereotype.Service;
import yfdc.GsonFactory;
import yfdc.JavaBean;
import java.util.*;

/**
 * @author LiLinnan
 * @version 1.0
 * @date 2020/1/23 20:37
 */
@Service public final class GradeSearchServiceImpl extends GradeSearchService {
	@Override
	public final String getServName() {
		return "成绩搜索服务";
	}

	private final Gson gson;

	public GradeSearchServiceImpl() {
		super();
		gson = GsonFactory.getGson();
	}

	/**
	 * 查询全部的学期
	 *
	 * @param myOkHttpClient 用户客户端
	 * @return 学期列表
	 */
	@Override public final List<Term> searchTerm(MyOkHttpClient myOkHttpClient) {
		ArrayList<Term> terms = new ArrayList<>();
		//拿到客户端
		OkHttpClient client = myOkHttpClient.client;
		//拿到端口
		int port = myOkHttpClient.port;
		//创建查询学期的请求
		Request request = new Request.Builder().url(UrlValue.termGetUrl(port)).build();
		//执行请求
		String result = getResult(client, request);
		if (result == null) {
			return null;
		}
		//解析为Document
		Document document = Jsoup.parse(result);
		//取select
		Element select = null;
		try {
			select = document.select("#zxjxjhh").get(0);
		} catch (Throwable e) {
			e.printStackTrace(System.out);
			return terms;
		}
		for (Element element : select.children()) {
			String termName = element.html();
			String termId = element.attr("value");
			terms.add(new Term(termId, termName));
		}
		return terms;
	}

	/**
	 * 查询本学期成绩
	 *
	 * @param myOkHttpClient 用户客户端
	 * @return 成绩列表
	 */
	@Override public final List<TermGrade> searchCurrentTermGrade(@NotNull MyOkHttpClient myOkHttpClient) {
		Intrinsics.checkParameterIsNotNull(myOkHttpClient,"myOkHttpClient");
		ArrayList<TermGrade> termGrades = new ArrayList<TermGrade>(1);

		//成绩表
		ArrayList<Grade> gradeArrayList = new ArrayList<Grade>();

		TermGrade termGrade = new TermGrade("本学期成绩", gradeArrayList);
		termGrades.add(termGrade);

		//拿到客户端
		OkHttpClient client = myOkHttpClient.client;
		//拿到端口
		int port = myOkHttpClient.port;
		//创建查询全部成绩的请求
		Request request = new Request.Builder().url(UrlValue.currentTermGradeGetUrl(port)).build();
		//执行请求
		String json = getResult(client, request);
		if (json == null) {
			return null;
		}
		//本学期成绩对象
		CurrentTermGrade[] currentTermGrade = null;
		try{
			currentTermGrade = gson.fromJson(json, CurrentTermGrade[].class);
		}catch (Throwable ex){
			java.io.File f = null;
			java.io.FileWriter w = null;
			try{
				f = new java.io.File("./error.txt");
				if (((!f.exists()) && (f.createNewFile()))||(f.exists())) {
					System.out.println("success");
					w = new java.io.FileWriter(f);
					w.write(json);
					w.write("\n");
					w.write(JavaBean.stackTrace(ex));
					w.close();
				}
			}catch (Throwable ignor){
				//ignored
			}
			ex.printStackTrace(System.out);
			return null;
		}
		//不存在成绩列表，返回空列表
		if (currentTermGrade.length <= 0) {
			return termGrades;
		}
		//拿到成绩表
		List<CurrentTempGrade> currentTempGrades = currentTermGrade[0].getList();
		for (CurrentTempGrade currentTempGrade : currentTempGrades) {
			Grade grade = new Grade();
			//先把分数放上去
			grade.setScore(currentTempGrade.getCourseScore());
			//课程名称
			grade.setCourseName(currentTempGrade.getCourseName());
			//课程号
			grade.setCourseNumber(currentTempGrade.getId().getCourseNumber());
			//创建课程详情列表
			ArrayList<GradeDetail> gradeDetailList = new ArrayList<>();
			//放进去
			grade.setDetails(gradeDetailList);
			//添加到成绩表中
			gradeArrayList.add(grade);
			if (grade.getScore().trim().length() == 0) {
				grade.setScore("-1");
				continue;
			}
			String failReason = currentTempGrade.getUnpassedReasonExplain().trim();
			grade.setFailReason(failReason.length() == 0 ? "无" : failReason);
			System.out.println(currentTempGrade.getFxcjId());
			FormBody formBody = new FormBody.Builder().add("fxcjId", currentTempGrade.getFxcjId())
					.add("pageNum", "1")
					.add("pageSize", "1000").build();
			//创建请求详情数据的request
			request = new Request.Builder().url(UrlValue.gradeDetailUrlGetUrl(port)).post(formBody).build();
			//进行请求
			json = getResult(client, request);
			//将拿到的json串进行解析，并放到成绩表中
			int result = jsonToDetail(json, gradeDetailList);
			if (result == -1) {
				return null;
			}
		}
		return termGrades;
	}

	/**
	 * 查询历年学期的成绩
	 *
	 * @param searchCondition 查询条件
	 * @param myOkHttpClient  用户客户端
	 * @return 成绩列表
	 */
	@Override
	public List<TermGrade> searchAllTermGrade(MyOkHttpClient myOkHttpClient, SearchCondition searchCondition) {
		//termGrade
		ArrayList<TermGrade> termGrades = new ArrayList<>();
		//拿到客户端
		OkHttpClient client = myOkHttpClient.client;
		//拿到端口
		int port = myOkHttpClient.port;

		//创建查询全部成绩的请求
		Request request = new Request.Builder().url(UrlValue.allTermGradeGetUrl(port)).post(getSearchAllFormBodyForSearchAll(searchCondition)).build();
		//执行请求
		String json = getResult(client, request);
		if (json == null) {
			return null;
		}
		AllTermGrade allTermGrade = null;
		try {
			allTermGrade = gson.fromJson(json, AllTermGrade.class);
		} catch (Throwable w) {
			w.printStackTrace(System.out);
			return null;
		}
		List<List<Object>> courses = allTermGrade.getList().getRecords();
		HashSet<String> hashSet = new HashSet<>();
		//开始
		for (List<Object> course : courses) {
			try {
				String termId = course.get(0).toString();
				int sizeBefore = hashSet.size();
				hashSet.add(termId);
				if (hashSet.size() != sizeBefore) {
					//证明是一个新的学期
					//创建，然后放进去
					termGrades.add(new TermGrade(termId, new ArrayList<>()));
				}
				//找到自己所属的学期
				TermGrade termGrade = null;
				for (TermGrade temp : termGrades) {
					String termGradeTermId = temp.getTermId();
					if (termGradeTermId.equals(termId)) {
						termGrade = temp;
						break;
					}
				}
				if (termGrade == null) {
					continue;
				}
				//找到后
				List<Grade> gradeList = termGrade.getGrades();
				Grade grade = getSearchAllGrade(course);
				gradeList.add(grade);
				//创建请求详情数据的request
				request = new Request.Builder().url(UrlValue.gradeDetailUrlGetUrl(port)).post(getSearchAllFormBodyForSearchFxcj(course)).build();
				//进行请求
				json = getResult(client, request);
				//将拿到的json串进行解析，并放到成绩表中，
				int result = jsonToDetail(json, grade.getDetails());
				if (result == -1) {
					return null;
				}
			} catch (Throwable e) {
				e.printStackTrace(System.out);
			}
		}
		//进行排序
		Collections.sort(termGrades);
		return termGrades;
	}

	/**
	 * 为查询所有的全部成绩查询创建表单
	 *
	 * @param searchCondition 查询条件
	 * @return 创建好的表单
	 */
	private static FormBody getSearchAllFormBodyForSearchAll(@NotNull SearchCondition searchCondition) {
		Intrinsics.checkParameterIsNotNull(searchCondition,"searchCondition");
		return new FormBody.Builder()
				.add("zxjxjhh", searchCondition.getTermId())
				.add("kch", searchCondition.getCourseNumber())
				.add("kcm", searchCondition.getCourseName())
				.add("pageNum", "1")
				.add("pageSize", "1000").build();
	}


	/**
	 * 将查询所有的结果转换为Grade
	 *
	 * @param course 课程list
	 * @return Grade
	 */
	private Grade getSearchAllGrade(List<Object> course) {
		Grade grade = new Grade();
		//先把分数放上去
		//分数肯定是有的，不可能为其他值
		grade.setScore(course.get(8).toString());
		//课程名称
		grade.setCourseName(course.get(11).toString());
		//课程号
		grade.setCourseNumber(course.get(1).toString());
		//创建课程详情列表
		ArrayList<GradeDetail> gradeDetailList = new ArrayList<>();
		//放进去
		grade.setDetails(gradeDetailList);
		Object o = course.get(18);
		if (o != null) {
			String reason = o.toString().trim();
			grade.setFailReason(reason.length() == 0 ? "无" : reason);
		}
		return grade;
	}


	/**
	 * 为查询所有的分项成绩查询计算分项成绩id
	 *
	 * @param course 课程list
	 * @return id
	 */
	private String getSearchAllFxcjId(List<Object> course) {
		return course.get(0) + "_" +
				course.get(1) + "_" +
				course.get(2) + "_" +
				course.get(3) + "_" +
				course.get(5);
	}

	/**
	 * 为查询所有的分项成绩查询创建表单
	 *
	 * @param course 课程list
	 * @return 表单
	 */
	private FormBody getSearchAllFormBodyForSearchFxcj(List<Object> course) {
		return new FormBody.Builder().add("fxcjId", getSearchAllFxcjId(course))
				.add("pageNum", "1")
				.add("pageSize", "1000").build();
	}


	@Override
	public List<TermGrade> searchFailTermGrade(MyOkHttpClient myOkHttpClient) {
		return null;
	}


	/**
	 * 是否掉登录了
	 *
	 * @param string 结果
	 * @return 是否掉登录了
	 */
	private boolean isOut(String string) {
		if (string == null) {
			return true;
		}
		String clickChangeOne = "点击换一张";
		return string.contains(clickChangeOne);
	}

	/**
	 * 进行网络请求
	 *
	 * @param client  okhttp客户端
	 * @param request 要发起的请求对象
	 * @return 拿到的请求结果，如果为null代表掉登录了
	 */
	private String getResult(OkHttpClient client, Request request) {
		try {
			String result = Objects.requireNonNull(client.newCall(request).execute().body()).string();
			if (isOut(result)) {
				return null;
			}
			return result;
		} catch (Throwable e) {
			e.printStackTrace(System.out);
			return null;
		}
	}
	private static void ignore(){}
	/**
	 * 将json详情成绩转换并放到list中
	 *
	 * @param json            拿到的json
	 * @param gradeDetailList 欲将数据放到的list
	 * @return 状态码
	 */

	private int jsonToDetail(String json, List<GradeDetail> gradeDetailList) {
		if (json == null) {
			return -1;
		}
		Detail detail = null;
		try {
			detail = gson.fromJson(json, Detail.class);
		} catch (Throwable www) {
			java.io.File f = new java.io.File("E:\\123\\cjcx\\!)tmperrpp.log");
			java.io.FileWriter w;
			try{
				if(!f.exists()) System.out.println(Boolean.toString(f.createNewFile()));
				w = new java.io.FileWriter(f);
				w.write(json);
				w.append("\n");
				w.append(yfdc.JavaBean.stackTrace(www));
				w.close();
				f = null;
				w = null;
			}catch (Throwable expv0x001){
				ignore();
				//ignore
			}
			www.printStackTrace(System.out);
			return -1;
		}
		List<Records> records = detail.getRecords();
		if (records == null) {
			return 0;
		}
		for (Records record : records) {
			GradeDetail gradeDetail = new GradeDetail();
			gradeDetail.setName(record.getCJFXMC());
			gradeDetail.setScore(record.getFXCJ());
			String weight = record.getCJFXZB();
			weight = "1".equals(weight.trim()) ? "1" : "0" + weight;
			gradeDetail.setWeight(weight);
			gradeDetailList.add(gradeDetail);
		}
		return 1;
	}
}
